﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ionic.Zip;
using System.IO;
using HU8.Helpers.Base;

namespace HU8.Helpers.Files
{
    public class ZipHelper
    {
        #region zip
        ///压缩，解压缩文件夹，我使用了Ionic的Zip处理dll
        ///http://dotnetzip.codeplex.com/
        ///http://cheeso.members.winisp.net/DNZHelp/


        /// <summary>
        /// 压缩指定文件集合
        /// </summary>
        /// <param name="files"></param>
        /// <param name="saveTo"></param>
        public static JsonResponse GenerateZipFile(string files, string saveTo, string comment, bool includeRoot = true)
        {
            List<string> fileList = files.Split(',').ToList();
            return GenerateZipFile(fileList, saveTo, comment, includeRoot);
        }

        public static JsonResponse GenerateZipFile(List<string> files, string saveTo, string comment, bool includeRoot = true)
        {
            return GenerateZipFile(files, saveTo, comment, "", includeRoot);
        }

        public static JsonResponse GenerateZipFile(List<string> files, string saveTo, string comment, string exceptions, bool includeRoot = true)
        {
            JsonResponse response = new JsonResponse();
            try
            {
                using (ZipFile zip = new ZipFile())
                {
                    zip.AlternateEncoding = System.Text.Encoding.UTF8;
                    zip.AlternateEncodingUsage = ZipOption.Always;
                    zip.Comment = comment;

                    foreach (string f in files)
                    {
                        if (File.Exists(f))
                        {
                            FileInfo fi = new FileInfo(f);
                            if (BaseHelper.IsNotInException(fi.Name, exceptions))
                            {
                                zip.AddFile(f, "");
                            }
                        }
                        else if (Directory.Exists(f))
                        {
                            DirectoryInfo di = new DirectoryInfo(f);
                            if (BaseHelper.IsNotInException(di.Name, exceptions))
                            {
                                if (files.Count == 1 && !includeRoot)
                                {
                                    //如果要忽略顶层文件夹
                                    ZipFolder("", f, zip, exceptions, false);
                                }
                                else
                                {
                                    zip.AddDirectoryByName(di.Name);
                                    ZipFolder("", f, zip, exceptions, true);
                                }
                            }
                        }
                        else
                        {
                            //不存在
                        }
                    }
                    zip.Save(saveTo);
                    FileInfo savedFile = new FileInfo(saveTo);

                    response.success = true;
                    response.message = string.Format("{0}压缩文件夹生成成功", savedFile.Name);
                }
            }
            catch (Exception ex)
            {
                response.success = false;
                response.message = string.Format("Zip生成失败：{0}", ex.Message);
            }
            return response;
        }

        /// <summary>
        /// 压缩文件夹
        /// </summary>
        /// <param name="previousPath"></param>
        /// <param name="dir"></param>
        /// <param name="zip"></param>
        private static void ZipFolder(string previousPath, string dir, ZipFile zip, string exceptions, bool includeRoot)
        {
            DirectoryInfo di = new DirectoryInfo(dir);
            if (includeRoot)
            {
                //如果不
                previousPath += previousPath.EndsWith("/") ? "" : "/" + di.Name;
            }
            foreach (FileInfo fi in di.GetFiles())
            {
                string fPath = previousPath +  (previousPath.EndsWith("/") ? "" : "/") + fi.Name;
                if (BaseHelper.IsNotInException(fPath, exceptions))
                {
                    zip.AddFile(fi.FullName, previousPath);
                }
            }
            foreach (DirectoryInfo d in di.GetDirectories())
            {
                string dPath = previousPath + (previousPath.EndsWith("/") ? "" : "/") + d.Name + "/";
                if (BaseHelper.IsNotInException(dPath, exceptions))
                {
                    zip.AddDirectoryByName(dPath);
                    ZipFolder(previousPath, d.FullName, zip, exceptions, true);
                }
            }
        }


        /// <summary>
        /// 解压文件夹
        /// 解压的时候，结构是否也在？
        /// </summary>
        /// <param name="file">文件</param>
        /// <param name="unzipTo">解压到</param>
        /// <param name="overwrite">是否覆盖</param>
        public static JsonResponse UnzipFile(string file, string unzipTo, bool overwrite)
        {
            return UnzipFile(file, unzipTo, overwrite, "");
        }

        /// <summary>
        /// 解压文件
        /// </summary>
        /// <param name="file">压缩文件</param>
        /// <param name="unzipTo">解压到</param>
        /// <param name="overwrite">覆盖</param>
        /// <param name="exceptions">不解压的文件</param>
        public static JsonResponse UnzipFile(string file, string unzipTo, bool overwrite, string exceptions)
        {
            JsonResponse response = new JsonResponse();
            try
            {
                using (ZipFile zip = ZipFile.Read(file))
                {
                    foreach (ZipEntry e in zip)
                    {
                        if (BaseHelper.IsNotInException("/" + e.FileName, exceptions)) //如果不在不解压列表中
                        {
                            e.AlternateEncoding = System.Text.Encoding.UTF8;
                            e.AlternateEncodingUsage = ZipOption.Always;
                            e.Extract(unzipTo, overwrite ? ExtractExistingFileAction.OverwriteSilently : ExtractExistingFileAction.DoNotOverwrite);
                        }
                    }
                }
                response.message = "解压缩成功";
                response.success = true;
            }
            catch (Exception ex)
            {
                response.message = ex.Message;
                response.success = false;
            }
            return response;
        }

        /// <summary>
        /// 获得ZIP的信息，包括结构信息
        /// </summary>
        /// <param name="file">文件路径</param>
        /// <param name="showHeader">显示ZIP的头部信息</param>
        /// <returns></returns>
        public static string GetZipInfo(string file)
        {
            string info = "";
            using (ZipFile zip = ZipFile.Read(file))
            {

                info += string.Format("<h1>Zipfile: {0}</h1>", zip.Name);
                if ((zip.Comment != null) && (zip.Comment != ""))
                    info += string.Format("<p>Comment: {0}</p>", zip.Comment);
                info += string.Format("<table></thead><tr><th>{0}</th><th>{1}</th><th>{2}</th><th>{3}</th><th>{4}</th><th>{5}</th></tr></thead>",
                                        "Filename", "Modified", "Size", "Ratio", "Packed", "pw?");
                info += "<tbody>";
                foreach (ZipEntry e in zip)
                {

                    info += string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td></tr>",
                    e.FileName,
                    e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
                    e.UncompressedSize,
                    e.CompressionRatio,
                    e.CompressedSize,
                    (e.UsesEncryption) ? "Y" : "N");
                }
                info += "</tbody>";
                info += "</table>";
            }
            return info;
        }
        #endregion
    }
}
